package com.hn.zhijian.base.common.converter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.hn.zhijian.base.common.StatusCode;
import com.hn.zhijian.base.model.response.IgnoreResponse;
import com.hn.zhijian.base.model.response.Response;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import java.lang.reflect.AnnotatedElement;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

/**
 * @author carl chen
 * @Classname ResultHandler
 * @Description JSON统一返回 SpringBoot模式下使用 原理拦截 RestController ResponseBody 两个注解
 * @Date 2019/10/30 11:21
 */
@Slf4j
@ControllerAdvice(annotations = {RestController.class, ResponseBody.class})
public class ResultHandler implements ResponseBodyAdvice {

    public static final String SPRING_CLOUD_TAG = "CLOUD";

    @Autowired
    private ObjectMapper objectMapper;

    private ThreadLocal<ObjectMapper> mapperThreadLocal = ThreadLocal.withInitial(ObjectMapper::new);

    private static final Class[] ANNIS = {
            RequestMapping.class,
            GetMapping.class,
            PostMapping.class,
            DeleteMapping.class,
            PutMapping.class
    };

    @Override
    public boolean supports(MethodParameter methodParameter, Class aClass) {
        AnnotatedElement element = methodParameter.getAnnotatedElement();
        return Arrays.stream(ANNIS).anyMatch(anno -> anno.isAnnotation() && element.isAnnotationPresent(anno));
    }

    @Override
    public Object beforeBodyWrite(@Nullable Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse responses) {
        Object result = "";
        boolean isSpringCloud =Optional.ofNullable(request.getHeaders().get(SPRING_CLOUD_TAG)).map(strings -> strings.equals(SpringCloudTag.YES.name())).orElse(false);
        if ((body instanceof IgnoreResponse) || isSpringCloud) {
            return body;
        } else if (body instanceof List) {
            List list = (List) body;
            if (list != null && !list.isEmpty() && list.get(0) instanceof IgnoreResponse) {
                return body;
            } else {
                result = new Response(StatusCode.OK.getCode(), StatusCode.OK.getMessage(), body);
            }
        }else {
            result = new Response(StatusCode.OK.getCode(), StatusCode.OK.getMessage(), body);
        }
        return result;
    }

    public static void main(String[] args) {
        String tag = "OK";
        System.out.println(SpringCloudTag.YES.name());
        System.out.println();
    }
}
